package com.jinxin.platform.cdinfogo.rpc;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jinxin.platform.base.common.pojo.InvokeCfg;
import com.jinxin.platform.base.common.pojo.JsonResult;
import com.jinxin.platform.base.common.support.BusinessDelegate;
import com.jinxin.platform.cdinfogo.mapper.CdinfogoLedModuleMapper;
import com.jinxin.platform.cdinfogo.mapper.CdinfogoLedProgramMapper;
import com.jinxin.platform.cdinfogo.pojo.domain.CdinfogoDevice;
import com.jinxin.platform.cdinfogo.pojo.domain.CdinfogoLedModule;
import com.jinxin.platform.cdinfogo.pojo.domain.CdinfogoLedProgram;
import com.jinxin.platform.cdinfogo.pojo.vo.Constant;
import com.jinxin.platform.cdinfogo.pojo.vo.DictEntity;
import com.jinxin.platform.cdinfogo.pojo.vo.ModeInfo;
import com.jinxin.platform.cdinfogo.pojo.vo.SysUserVO;
import com.jinxin.platform.cdinfogo.utils.URLEncoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author : zhangpeng
 * @date : 2021-06-29 23:42:13
 **/
@Component
@Slf4j
public class CdInfoGoRpcService {

    @Resource
    private BusinessDelegate businessDelegate;
    @Autowired
    private CdinfogoLedProgramMapper ledProgramMapper;
    @Autowired
    private CdinfogoLedModuleMapper ledModuleMapper;
    @Autowired
    private PlatformTransactionManager transactionManager;

    /**
     * 获取当前用户对象
     *
     * @return SysUser
     */
    public SysUserVO getCurrentUser() {
        JsonResult result = getJsonResult(Constant.MODULE_KEY, "getCurrentUser");
        if (result.getSuccess()) {
            if (result.getData() == null) {
                return null;
            }
            return JSON.parseObject(JSON.toJSONString(result.getData()), SysUserVO.class);
        }
//        SysUserVO sysUserVO = new SysUserVO();
//        sysUserVO.setUserAccount("admin");
//        sysUserVO.setUserCellphoneNo("15723013583");
//        sysUserVO.setUserCardId("510823199604025671");
//        sysUserVO.setUserType("1");
//        sysUserVO.setUserName("dd");
//        sysUserVO.setOrgId("32123");
//        return sysUserVO;
        return null;
    }

    // 新增模式
    public JsonResult addMode(String account,String msmls,String modeName,CdinfogoLedProgram program){
        Map<String,String> map = new HashMap<>();
        map.put("account",account);//BCCA账号
        map.put("enableMode","yes");//激活
        map.put("msmls",msmls);//命令集合
        map.put("modeName",modeName);//产品名称
        InvokeCfg cfg = new InvokeCfg();
        cfg.setModuleKey(Constant.MODULE_KEY);
        cfg.setClassName(Constant.MODULE_CLASS_NAME);
        cfg.setFunName("addMode");
        cfg.setArgs(map);
        log.info("[信息发布模块]新增模式[命令集合]参数 " + msmls);
        JsonResult result = businessDelegate.invoke(cfg);
        log.info("[信息发布模块]新增模式 " + result.toString());
        if(result.getSuccess()){
            //data: {"ymsid":"1476805027061395458","modeCommandList":[{"cmdPapam":"none","modeId":"264764309907832832","createId":"ee1bb855dd4844439af444df7dbc3824","id":"264764309907832833","createDate":1640932730000}],"enableMode":"yes","createId":"ee1bb855dd4844439af444df7dbc3824","checked":false,"id":"264764309907832832","account":"1565100000001203","createDate":1640932730978}
            ModeInfo modeInfo = JSON.parseObject(JSON.toJSONString(result.getData()), ModeInfo.class);
            if(modeInfo != null && !StringUtils.isEmpty(modeInfo.getModeName())){
                program.setModeId(modeInfo.getModeId());
                program.setYmsid(modeInfo.getYmsid());
                int n = saveProgram(program, program.getModuleList());
                return n > 0 ? JsonResult.ok("生成模式成功",null) : JsonResult.error("生成模式失败");
            }
        }
        return JsonResult.error("生成模式失败,原因是：" + result.getMsg());
    }

    // 删除模式
    public JsonResult deleteMode(String account,String ymsid,String modeId,String programId,String mac){
        HashMap param = new HashMap();
        param.put("modeId",modeId);
        param.put("ymsid",ymsid);
        CdinfogoLedProgram ledProgram = ledProgramMapper.selectOne(param);
        if(ledProgram == null){return JsonResult.error("模式不存在");}
        Map<String,String> map = new HashMap<>();
        map.put("account",account);//BCCA账号
        map.put("ymsid",ymsid);//云模式ID
        map.put("id",modeId);//本地模式ID
        InvokeCfg cfg = new InvokeCfg();
        cfg.setModuleKey(Constant.MODULE_KEY);
        cfg.setClassName(Constant.MODULE_CLASS_NAME);
        cfg.setFunName("deleteMode");
        cfg.setArgs(map);
        JsonResult result = businessDelegate.invoke(cfg);
        log.info("[信息发布模块]删除模式返回" + result.toString());
        if(result.getSuccess()){
            DefaultTransactionDefinition def = new DefaultTransactionDefinition();
            def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);//新发起一个事务
            TransactionStatus transaction = transactionManager.getTransaction(def);
            ledProgramMapper.removeMode(ledProgram.getId());
            //删除网关节目
            JsonResult jsonResult = removeProgram("", programId, mac);
            if(jsonResult.getSuccess()){
                transactionManager.commit(transaction);
                return JsonResult.ok("删除模式成功",null);
            }else {
                transactionManager.rollback(transaction);
                return JsonResult.error(jsonResult.getMsg());
            }
        }
        return JsonResult.error(result.getMsg());
    }

    private int saveProgram(CdinfogoLedProgram program,List<CdinfogoLedModule> moduleList){
        int result = 0;
        String programId = program.getId();
        String mac = program.getMac();
        CdinfogoLedProgram ledProgram = ledProgramMapper.selectByKey(programId);
        if(ledProgram == null){
            Integer maxXh = ledProgramMapper.selectMaxXhByMac(mac);
            int xh = maxXh == null ? 1 : maxXh + 1;
            program.setXh(xh);
            int n = ledProgramMapper.insert(program);
            if(n > 0){
                List<CdinfogoLedModule> newModuleList = new ArrayList<>();
                for(int j=0;j<moduleList.size();j++){
                    CdinfogoLedModule module = moduleList.get(j);
                    module.setXh((j+1));
                    module.setProgramId(programId);
                    newModuleList.add(module);
                }
                if(newModuleList.size() == 0){
                    result++;
                }else {
                    int count = ledModuleMapper.insertBatch(newModuleList);
                    if(count > 0){
                        result++;
                    }
                }
            }
        }else {
            int count = ledProgramMapper.updateByKey(program);
            if(count > 0){
                for (int j = 0; j < moduleList.size(); j++) {
                    CdinfogoLedModule module = moduleList.get(j);
                    module.setXh((j+1));
                    CdinfogoLedModule ledModule = ledModuleMapper.selectByKey(module.getId());
                    int r = 0;
                    if(ledModule == null){
                        r += ledModuleMapper.insert(module);
                    }else {
                        r += ledModuleMapper.updateByKey(module);
                    }
                    if(r > 0){
                        result++;
                    }
                }
            }
        }
        return result;
    }

    /**
     * 获取当前系统的BCCA账号(多个)
     *
     * @return SysUser
     */
    public List<String> getBccaAccounts() {
        Map<String,String> map = new HashMap<>();
        map.put("status","1");
        InvokeCfg cfg = new InvokeCfg();
        cfg.setModuleKey(Constant.MODULE_KEY);
        cfg.setClassName(Constant.MODULE_CLASS_NAME);
        cfg.setFunName("getBccaAccounts");
        cfg.setArgs(map);
        JsonResult result = businessDelegate.invoke(cfg);
        log.info("获取当前系统的BCCA账号 " + result.toString());
        List<String> bccaList = new ArrayList<>();
        if(result.getSuccess()){
            if (result.getData() == null){
                return null;
            }
            JSONArray jsonArray = JSON.parseArray(result.getData().toString());
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                if(jsonObject != null){
                    bccaList.add(jsonObject.getString("bccaAccount"));
                }
            }
        }
        return bccaList;
    }
    /**
     * 获取模块绑定的设备
     * @param
     * @return
     */
    public List<CdinfogoDevice> getDevice(){
        Map<String,String> map = new HashMap<>();
        map.put("moduleCode","apcos-cdinfogo");
        InvokeCfg cfg = new InvokeCfg();
        cfg.setModuleKey(Constant.MODULE_KEY);
        cfg.setClassName(Constant.MODULE_CLASS_NAME);
        cfg.setFunName("getDevice");
        cfg.setArgs(map);
        JsonResult invoke = businessDelegate.invoke(cfg);
        log.info("获取设备:{}", JSON.toJSONString(invoke));
        if (invoke.getSuccess()){
            if (invoke.getData() == null){
                return null;
            }
            return JSON.parseArray(JSON.toJSONString(invoke.getData()),CdinfogoDevice.class);
        }
        return null;
    }

    /**
     * 获取字典模块关于考勤班组的内容
     */
    public List<DictEntity> getDict(Map map) {
        InvokeCfg cfg = new InvokeCfg();
        cfg.setModuleKey(Constant.MODULE_KEY);
        cfg.setClassName("dictRpcService");
        cfg.setFunName("getBusinessModule");
        cfg.setArgs(map);
        JsonResult result = businessDelegate.invoke(cfg);
        log.info("result:" + result);
        if (result.getSuccess()) {
            if (result.getData() == null) {
                return null;
            }
            List<DictEntity> dictVos = JSON.parseArray(JSON.toJSONString(result.getData()).toString(), DictEntity.class);
            log.info("根据字典类型:{},获取到字典:{}", map, dictVos);
            return dictVos;
        }
//        else {
//            DictEntity dictVo = new DictEntity();
//            dictVo.setDictKey("1");
//            dictVo.setDictValue("测试一组");
//            DictEntity dictVo1 = new DictEntity();
//            dictVo1.setDictKey("2");
//            dictVo1.setDictValue("测试二组");
//            List<DictEntity> list = new ArrayList<>();
//            list.add(dictVo);
//            list.add(dictVo1);
//            return list;
//        }
        log.info("未获取字典内容");
        return null;
    }

    //控制设备
    public JsonResult controlDevice(CdinfogoDevice deviceInfoDO, String controlParams, String operation) {
        InvokeCfg cfg = new InvokeCfg();
        cfg.setModuleKey(Constant.MODULE_KEY);
        cfg.setClassName(Constant.MODULE_CLASS_NAME);
        cfg.setFunName("controlDevice");
        HashMap<String, String> resultMap = new HashMap<>();
        resultMap.put("controlParams", controlParams);
        resultMap.put("operation", operation);
        resultMap.put("serial_num", deviceInfoDO.getDeviceMac());
        resultMap.put("productId", deviceInfoDO.getDeviceType());
        cfg.setArgs(resultMap);
        log.info("led发送参数：{}",JSON.toJSONString(resultMap));
        JsonResult jsonResult = businessDelegate.invoke(cfg);
        log.info("controlDeviceResult--------" + jsonResult);
        return jsonResult;
    }

    private JsonResult controlDevice(String operation, String mac,String controlParams) {
        CdinfogoDevice cdinfogoDevice = new CdinfogoDevice();
        cdinfogoDevice.setDeviceMac(mac);
        return controlDevice(cdinfogoDevice,controlParams,operation);
    }

    public Integer getItems(String name){
        Map<String,String> map = new HashMap<>();
        map.put("itemName",name);

        InvokeCfg cfg = new InvokeCfg();
        cfg.setModuleKey(Constant.MODULE_KEY);
        cfg.setClassName(Constant.MODULE_CLASS_NAME);
        cfg.setFunName("getItems");
        cfg.setArgs(map);
        JsonResult invoke = businessDelegate.invoke(cfg);
        log.info("获取进入人数:{}", JSON.toJSONString(invoke));
        if (invoke.getSuccess()){
            if (invoke.getData() == null){
                return 0;
            }
            try{
                JSONObject jsonObject = JSON.parseObject(invoke.getData().toString());
                return Integer.parseInt(jsonObject.get("count").toString());
            }catch (Exception e){
                log.info("获取人数异常:{}",e.toString());
                return 0;
            }
        }
        return 0;
    }

    private JsonResult getJsonResult(String keyName, String funName) {
        InvokeCfg cfg = new InvokeCfg();
        cfg.setModuleKey(keyName);
        cfg.setClassName(Constant.MODULE_CLASS_NAME);
        cfg.setFunName(funName);
        JsonResult invoke = businessDelegate.invoke(cfg);
        log.info("获取数据:{}", JSON.toJSONString(invoke));
        return invoke;
    }

    /**
     * 发送数据到led屏
     * @param port LED端口号
     * @param dataStr 发送数据
     * @param mac  设备mac
     * @return
     */
    public JsonResult sendToScreen(String port,String dataStr,String mac) {
        if(StringUtils.isEmpty(port)){
            port = Constant.DEFAULT_LED_PORT;
        }
        if(StringUtils.isEmpty(dataStr)){
            return JsonResult.error("发送数据不存在");
        }
        JSONObject pJsonObj = new JSONObject();
        pJsonObj.put("p1",port);
        pJsonObj.put("p2",dataStr);
        JsonResult result = controlDevice(Constant.CMD_SEND_TO_SCREEN,mac, URLEncoder.encodeURIComponent(pJsonObj.toJSONString()));
        log.info("LED模块模块控制(发送数据到led屏)返回："+result.toString());
        // data={"code":"0","r1":"ok"}
        String resultStr = result.getData().toString();
        if (isSucceed2(resultStr)) {
            return JsonResult.ok("发送数据到led屏成功",result.getData());
        }else {
            return JsonResult.error("发送数据到led屏失败,原因是: " + getErrorMsg(resultStr));
        }
    }

    /**
     * 将节目数据保存到网关
     * @param port       LED端口号
     * @param programId  节目ID
     * @param dataStr    节目数据
     * @param mac        设备mac
     * @return
     */
    public JsonResult saveProgram(String port,String programId,String dataStr,String mac) {
        if(StringUtils.isEmpty(port)){
            port = Constant.DEFAULT_LED_PORT;
        }
        if(StringUtils.isEmpty(programId)){
            return JsonResult.error("节目ID不存在");
        }
        if(StringUtils.isEmpty(dataStr)){
            return JsonResult.error("节目数据不存在");
        }
        JSONObject pJsonObj = new JSONObject();
        pJsonObj.put("p1",port);
        pJsonObj.put("p2",programId);
        pJsonObj.put("p3",dataStr);
        JsonResult result = controlDevice(Constant.CMD_SAVE_PROGRAM,mac, URLEncoder.encodeURIComponent(pJsonObj.toJSONString()));
        log.info("LED模块模块控制(节目数据保存到网关)返回："+result.toString());
        // data={"code":"0","r1":"ok"}
        String resultStr = result.getData().toString();
        if (isSucceed2(resultStr)) {
            return JsonResult.ok("节目数据保存到网关成功",result.getData());
        }else {
            return JsonResult.error("节目数据保存到网关失败,原因是: " + getErrorMsg(resultStr));
        }
    }

    public JsonResult removeProgram(String port,String programId,String mac) {
        if(StringUtils.isEmpty(port)){
            port = Constant.DEFAULT_LED_PORT;
        }
        if(StringUtils.isEmpty(programId)){
            return JsonResult.error("节目ID不存在");
        }
        JSONObject pJsonObj = new JSONObject();
        pJsonObj.put("p1",port);
        pJsonObj.put("p2",programId);
        JsonResult result = controlDevice(Constant.CMD_REMOVE_PROGRAM,mac, URLEncoder.encodeURIComponent(pJsonObj.toJSONString()));
        log.info("LED模块模块控制(删除网关节目)返回："+result.toString());
        // data={"code":"0","r1":"ok"}
        String resultStr = result.getData().toString();
        if (isSucceed2(resultStr)) {
            return JsonResult.ok("删除网关节目成功",result.getData());
        }else {
            return JsonResult.error("删除网关节目失败,原因是: " + getErrorMsg(resultStr));
        }
    }

    /**
     * 获取控制卡参数(屏大小)
     * @param port LED端口号
     * @param mac  设备mac
     * @return
     */
    public JsonResult getBoardParam(String port,String mac) {
        if(StringUtils.isEmpty(port)){
            port = Constant.DEFAULT_LED_PORT;
        }
        if(StringUtils.isEmpty(mac)){
            return JsonResult.error("设备mac不存在");
        }
        JSONObject pJsonObj = new JSONObject();
        pJsonObj.put("p1",port);
        JsonResult result = controlDevice(Constant.CMD_Get_Board_Param,mac, pJsonObj.toJSONString());
        log.info("LED模块模块控制(获取控制卡参数(屏大小))返回："+result.toString());
        String resultStr = result.getData().toString();
        if (isSucceed(resultStr)) {
            //r1: "width=128 height=32 address=0 ip=192.168.60.222 mac=56-5a-00-01-41-b9
            // Server IP=255.255.255.255 Server Port=65535  Mask=255.255.255.255 Gateway=255.255.255.255
            // Name=led  Interval=65535 "
            String str = JSONObject.parseObject(result.getData().toString()).getString("r1");
            String[] resultArr = str.trim().split(" ");
            if(resultArr.length > 0){
                JSONObject obj = new JSONObject();
                obj.put("width",resultArr[0].replace("width=",""));
                obj.put("height",resultArr[1].replace("height=",""));
                return JsonResult.ok("获取控制卡参数(屏大小)成功",obj.toJSONString());
            }
        }

//        else {
//            String str= "width=128 height=32 address=0 ip=192.168.60.222 mac=56-5a-00-01-41-b9\n" +
//                    "             Server IP=255.255.255.255 Server Port=65535  Mask=255.255.255.255 Gateway=255.255.255.255\n" +
//                    "             Name=led  Interval=65535 ";
//            String[] resultArr = str.trim().split(" ");
//            if(resultArr.length > 0){
//                JSONObject obj = new JSONObject();
//                obj.put("width",resultArr[0].replace("width=",""));
//                obj.put("height",resultArr[1].replace("height=",""));
//                return JsonResult.ok("获取控制卡参数(屏大小)成功",obj.toJSONString());
//            }
//            //return JsonResult.error("设备控制错误,获取控制卡参数(屏大小)失败");
//        }
        return JsonResult.error("设备控制错误,获取控制卡参数(屏大小)失败");
    }

    /**
     * 校正时间
     * @param port LED端口号
     * @param mac  设备mac
     * @return
     */
    public JsonResult adjustTime(String port,String mac) {
        if(StringUtils.isEmpty(port)){
            port = Constant.DEFAULT_LED_PORT;
        }
        JSONObject pJsonObj = new JSONObject();
        pJsonObj.put("p1",port);
        JsonResult result = controlDevice(Constant.CMD_ADJUST_TIME,mac, pJsonObj.toJSONString());
        log.info("LED模块模块控制(校正时间)返回："+result.toString());
        // data={"code":"0","r1":"ok"}
        String resultStr = result.getData().toString();
        if (isSucceed2(resultStr)) {
            return JsonResult.ok("校正时间成功",result.getData());
        }else {
            return JsonResult.error("校正时间失败,原因是: " + resultStr);
        }
    }

    private boolean isSucceed(String result){
        if(StringUtils.isEmpty(result)){return false;}
        JSONObject returnJson = JSONObject.parseObject(result);
        if(returnJson == null){
            return false;
        }
        String responseCode = returnJson.getString("code");
        return "0".equals(responseCode);
    }

    private boolean isSucceed2(String result){
        if(StringUtils.isEmpty(result)){return false;}
        JSONObject returnJson = JSONObject.parseObject(result);
        if(returnJson == null){
            return false;
        }
        String responseCode = returnJson.getString("code");
        String r1 = returnJson.getString("r1");
        return "0".equals(responseCode) && "ok".equals(r1);
    }

    private String getErrorMsg(String result){
        if(StringUtils.isEmpty(result)){return "";}
        JSONObject returnJson = JSONObject.parseObject(result);
        if(returnJson == null){return "";}
        return returnJson.getString("r2");
    }

}
